<template>
  <div
    ref="echartsDom"
    class="pro-echarts-container"
    style="height: 100%; width: 100%"
  />
</template>
<script lang="ts" setup name="ProEcharts">
  import * as echarts from 'echarts'
  import { debounce } from 'lodash-es'
  import { useDarkThemeHook } from '@/utils/theme/setTheme'

  interface echartsPropsType {
    // echarts配置
    options: echarts.EChartsCoreOption | null | undefined
    // 是否适应黑暗模式
    openDarkTheme?: boolean
    loading?: boolean
    // loading样式
    loadingOptions?: Record<string, unknown>
    width?: number | undefined
    height?: number | undefined | '100%'
    // 当echarts宽高响应式变化时的动画延迟时间
    resizeDuration?: number
    // 改变options是否直接替换整个options，而不是和和旧数据合并
    optionsReplace?: boolean
  }

  const props = withDefaults(defineProps<echartsPropsType>(), {
    openDarkTheme: true,
    loading: false,
    width: undefined,
    height: '100%',
    resizeDuration: 300,
    optionsReplace: false
  })

  const dark = useDarkThemeHook()
  const echartsDom = ref<HTMLElement | null>(null)

  const emit = defineEmits(['beforeSetOptions'])

  // echarts 实例 非响应式
  let echartsInstance

  onMounted(() => {
    initEchartsInstance()
    initEchartsOptions()

    initWindowResize()
    initSidebarResize()
  })

  const initEchartsInstance = () => {
    if (!echartsDom.value) return
    // 是否开启暗黑主题
    echartsInstance = echarts.init(
      echartsDom.value,
      dark.value && props.openDarkTheme ? 'dark' : 'light',
      {
        height: props.height === '100%' ? undefined : props.height,
        width: props.width
      }
    )
    if (props.loading) showLoading()
    // 抛出设置完属性后的事件，可以用来设置添加事件监听等
    emit('beforeSetOptions', echartsInstance)
  }

  // 初始化配置
  const initEchartsOptions = () => {
    if (!echartsInstance || !props.options) return
    echartsInstance.setOption(props.options, props.optionsReplace)
  }

  // 销毁实例
  const dispose = () => {
    echartsInstance && echartsInstance.dispose()
    echartsInstance = null
  }

  const showLoading = () => {
    if (!echartsInstance) return
    echartsInstance.showLoading(props.loadingOptions)
  }

  const hideLoading = () => {
    if (!echartsInstance) return
    echartsInstance.hideLoading()
  }

  // 监听options
  watch(
    () => props.options,
    () => {
      initEchartsOptions()
    },
    {
      deep: true
    }
  )

  // 切换主题
  const toggleTheme = () => {
    if (!echartsInstance) return
    dispose()
    initEchartsInstance()
    initEchartsOptions()
  }

  // 切换是否适应黑暗模式
  watch(
    [() => props.openDarkTheme, () => props.height, () => props.width],
    () => {
      console.log('toggleTheme')

      toggleTheme()
    }
  )

  watch(dark, () => {
    props.openDarkTheme && toggleTheme()
  })

  // loading加载
  watch(
    () => props.loading,
    (val) => {
      val ? showLoading() : hideLoading()
    }
  )

  // 屏幕宽度自适应
  const resizeListener = debounce(() => {
    if (!echartsInstance) return
    echartsInstance.resize({
      animation: {
        duration: props.resizeDuration
      }
    })
  }, 200)

  const initWindowResize = () => {
    window.addEventListener('resize', resizeListener)
  }

  const removeWindowResize = () => {
    window.removeEventListener('resize', resizeListener)
  }

  // 左侧菜单栏宽度自适应

  const initSidebarResize = () => {
    const sidebarDom = document.getElementsByClassName('left')[0]
    sidebarDom && sidebarDom.addEventListener('transitionend', resizeListener)
  }

  const removeSidebarResize = () => {
    const sidebarDom = document.getElementsByClassName('left')[0]
    sidebarDom &&
      sidebarDom.removeEventListener('transitionend', resizeListener)
  }

  onUnmounted(() => {
    dispose()
    removeWindowResize()
    removeSidebarResize()
  })

  // keep-alive缓存
  onActivated(() => {
    resizeListener()
    initWindowResize()
    initSidebarResize()
  })

  onDeactivated(() => {
    removeWindowResize()
    removeSidebarResize()
  })

  defineExpose({
    // @Warn: echartsInstance 这个实例是非响应式的，因为echarts实例响应式会导致tooltip和legand显示异常
    echartsInstance,
    toggleTheme,
    dispose,
    initEchartsInstance,
    initEchartsOptions
  })
</script>
